#pragma once
#include "Rom.h"
#include "mapper/Mapper.h"

class Famicom;
class NesCartridge
{
private:

    typedef struct {
		uint8_t nes[4];
		uint8_t PRGBankCount;
		uint8_t CHRBankCount;
		uint8_t flag1;
		uint8_t flag2;
	}NesHeader;

	famicom_rom_t *mRom = nullptr;
	Famicom * famicom;
	bool mLoadedrom = false;
public:
	Mirror Mmirror = Mirror::SINGLE_SCREEN_LOWER;
	NesCartridge(Famicom *fc);

	~NesCartridge();

	uint8_t PRG_num();
	void ReleaseFcRom(famicom_rom_t* fcrom);

	famicom_rom_t* GetRom();

	bool IsLoadedRom();

	void Reset();
	bool CreateFcRom(famicom_rom_t** fcrom,void* data, size_t size);
	int LoadRom(famicom_rom_t* rom);


	void Save(SaveBundle* bundle);
	void Restore(SaveBundle* bundle);

	/// <summary>
	/// 垂直同步
	/// </summary>
	/// <param name="line"></param>
	inline void Hsync(uint32_t line) {
		mRom->mapper->Hsync(line);
	}

	/// <summary>
	/// CPU写入
	/// </summary>
	/// <param name="address"></param>
	/// <param name="data"></param>
	inline void WriteViaCPU(uint16_t address, uint8_t data)
	{
		mRom->mapper->WriteViaCPU(address, data);
	}

	/// <summary>
	/// CPU读取
	/// </summary>
	/// <param name="address"></param>
	/// <returns></returns>
	inline uint8_t ReadViaCPU(uint16_t address)
	{
		return mRom->mapper->ReadViaCPU(address);
	}

	/// <summary>
	/// PPU写入
	/// </summary>
	/// <param name="address"></param>
	/// <param name="data"></param>
	inline void WriteViaPPU(uint16_t address, uint8_t data)
	{
		mRom->mapper->WriteViaPPU(address, data);
	}

	/// <summary>
	/// PPU读取(0x8000 ~ 0x1FFF) 
	/// </summary>
	/// <param name="address"></param>
	/// <returns></returns>
	inline uint8_t ReadViaPPU(uint16_t address)
	{
		return mRom->mapper->ReadViaPPU(address);
	}

	/// <summary>
	/// 写入一个字节
	/// </summary>
	/// <param name="address"></param>
	/// <param name="data"></param>
	inline void Write6000(uint16_t address, uint8_t data)
	{
		mRom->mapper->Write6000(address, data);
	}

	/// <summary>
	/// 读取一个字节
	/// </summary>
	/// <param name="address"></param>
	/// <returns></returns>
	inline uint8_t Read6000(uint16_t address) {
		return mRom->mapper->Read6000(address);
	}



};


